import Bullet from "../../flyer/DefenseFlyer/DefenseBullet";
import HealthPoint, { Killer } from "../../funcObj/interface/HealthPoint";
import { GamePropType } from "../../info/GameEnum";
import NodePoolManager from "../../manager/NodePoolManager";
import PlayerManager from "../../manager/PlayerManager";
import Player from "../../player/Player";
import DefensiveFacility from "../DefensiveFacility";

const { ccclass, property } = cc._decorator;

/**
 * 普通近防炮
 */
@ccclass
export default class DefenseCannon extends DefensiveFacility {

    @property(cc.Node)
    gunBody: cc.Node = null;

    @property(cc.Sprite)
    tag: cc.Sprite = null;

    @property(cc.Label)
    levelLabel: cc.Label = null;

    @property(cc.Node)
    upgradeTip: cc.Node = null;

    @property([cc.SpriteFrame])
    gunBarrelFrames: cc.SpriteFrame[] = [];

    @property([cc.SpriteFrame])
    tagFrames: cc.SpriteFrame[] = [];

    time: number;

    public get shotRange(): number {
        let result = this.facilityInfo.每等级射程半径[this.level];
        if (this.player.props[GamePropType.超远程近防炮]) {
            result = Math.ceil(result * 1.5);
        }
        return result;
    }
    get shotSpeed(): number {
        if (this.player.props[GamePropType.速射近防炮]) {
            return this.facilityInfo.每等级射速[this.facilityInfo.每等级射速.length - 1];
        } else {
            return this.facilityInfo.每等级射速[this.level];
        }
    }

    init(player: Player): void {
        super.init(player);
        if (player.props[GamePropType.双管近防炮]) {
            this.gunBody.children[0].children[1].active = true;
        } else {
            this.gunBody.children[0].children[1].active = false;
        }

        this.time = 0;
        this.gunBody.position = cc.v3(0, 7)

        if (player == PlayerManager.instance.controllerPlayer) {
            this.onChangeDiamond(this.player.diamond);
            //监听
            this.player.node.on(Player.EventType.更新晶石, this.onChangeDiamond, this);
        } else {
            this.upgradeTip.active = false;
        }

        this.refresh();
    }

    onChangeDiamond(diamond: number) {
        let price = this.facilityInfo.每等级升级要求[this.level];
        this.upgradeTip.active = price && diamond >= price.diamond;
    }

    protected update(dt: number): void {
        let target: HealthPoint = this.getClosestTarget();
        if (!target) {
            this.time = 0;
            return;
        }

        //将炮口对准怪物
        let targetPosition = target.node.position;
        let direction = cc.v2(targetPosition.x - this.node.position.x, targetPosition.y - this.node.position.y);
        let angle = cc.misc.radiansToDegrees(cc.Vec2.angle(direction, cc.v2(0, 1)));
        this.gunBody.angle = direction.x > 0 ? 360 - angle : angle;
        //0.5秒射击一次
        this.time += dt;
        if (this.time > this.shotSpeed) {
            this.time = 0;
            this.shot(target);
        }
    }

    /**
     * 射击
     */
    shot(target: HealthPoint) {
        let flyerParent = this.player.flyerParentNode;
        let time = this.gunBody.children[0].children[1].active ? 2 : 1;

        for (let i = 0; i < time; i++) {
            let muzzle = this.gunBody.children[0].children[i].children[0];
            let bullet = NodePoolManager.instance.obtain(NodePoolManager.instance.defenceBullet);
            bullet.parent = flyerParent;
            bullet.position = bullet.parent.convertToNodeSpaceAR(muzzle.convertToWorldSpaceAR(cc.Vec3.ZERO));
            bullet.getComponent(Bullet).init(this, target);
        }

        let gunPosition = this.node.position;
        let dir = gunPosition.sub(target.node.position).normalize();
        let go = dir.mul(10 + this.level);

        cc.tween(this.gunBody)
            .by(0.1, { position: go }, { easing: "expoOut" })
            .to(0.1, { position: cc.v3(0, 7) }, { easing: "expoIn" })
            .start();
    }

    levelUp(): void {
        super.levelUp();
        this.refresh();
    }

    refresh() {
        this.tag.spriteFrame = this.tagFrames[this.player.playerId * 2 + (this.level > 2 ? 1 : 0)];
        this.gunBody.children[0].getComponentsInChildren(cc.Sprite).forEach(sprite => {
            sprite.spriteFrame = this.gunBarrelFrames[this.player.playerId * 3 + (this.level > 5 ? 2 : (this.level > 2 ? 1 : 0))]
            sprite.node.children[0].y = sprite.node.height * 0.9;
        });
        this.levelLabel.string = (this.level + 1).toString();
    }

    die(killer: Killer): void {
        super.die(killer);
        this.player.node.targetOff(this);
        this.intrudersFacility = null;
        this.intrudersFlyer = null;
        cc.Tween.stopAllByTarget(this.gunBody);
    }
}
